using Microsoft.AspNetCore.Mvc;
using Senparc.Weixin.Work.Tencent;
using System.Text;
using System.Xml;
using WeWorkApp.Api.Services;

namespace WeWorkApp.Api.Controllers
{
    /// <summary>
    /// 企业微信回调处理控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    public class CallbackController(
        ILogger<CallbackController> logger,
        IWeChatWorkService weChatWorkService,
        IConfiguration configuration)
        : ControllerBase
    {
        private readonly ILogger<CallbackController> _logger = logger;
        private readonly IWeChatWorkService _weChatWorkService = weChatWorkService;
        private readonly IConfiguration _configuration = configuration;

        /// <summary>
        /// 处理企业微信第三方应用回调验证
        /// </summary>
        /// <param name="msg_signature">企业微信加密签名</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        /// <param name="echostr">随机字符串</param>
        /// <returns></returns>
        [HttpGet("suite")]
        public Task<IActionResult> VerifySuiteCallback(
            [FromQuery] string msg_signature,
            [FromQuery] string timestamp,
            [FromQuery] string nonce,
            [FromQuery] string echostr)
        {
            try
            {
                _logger.LogInformation("收到企业微信第三方应用回调验证请求: msg_signature={MsgSignature}, timestamp={Timestamp}, nonce={Nonce}",
                    msg_signature, timestamp, nonce);

                var token = _configuration["SenparcWeixinSetting:Token"];
                var encodingAesKey = _configuration["SenparcWeixinSetting:EncodingAESKey"];
                var suiteId = _configuration["SenparcWeixinSetting:SuiteId"];

                if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(encodingAesKey) || string.IsNullOrEmpty(suiteId))
                {
                    _logger.LogError("企业微信配置信息不完整");
                    return Task.FromResult<IActionResult>(BadRequest("配置信息不完整"));
                }

                // 使用 WXBizMsgCrypt 验证签名并解密 echos tr
                var crypt = new WXBizMsgCrypt(token, encodingAesKey, suiteId);
                var resultEchos = string.Empty;
                var ret = crypt.VerifyURL(msg_signature, timestamp, nonce, echostr, ref resultEchos);


                if (ret == 0 && !string.IsNullOrEmpty(resultEchos))
                {
                    _logger.LogInformation("企业微信第三方应用回调验证成功");
                    return Task.FromResult<IActionResult>(Content(resultEchos));
                }
                else
                {
                    _logger.LogWarning("企业微信第三方应用回调验证失败，返回码：{Ret}", ret);
                    return Task.FromResult<IActionResult>(BadRequest("验证失败"));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理企业微信第三方应用回调验证时发生异常");
                return Task.FromResult<IActionResult>(StatusCode(500, "服务器内部错误"));
            }
        }

        /// <summary>
        /// 处理企业微信第三方应用回调事件
        /// </summary>
        /// <param name="msg_signature">企业微信加密签名</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        /// <returns></returns>
        [HttpPost("suite")]
        public async Task<IActionResult> HandleSuiteCallback(
            [FromQuery] string msg_signature,
            [FromQuery] string timestamp,
            [FromQuery] string nonce)
        {
            try
            {
                _logger.LogInformation("收到企业微信第三方应用回调事件: msg_signature={MsgSignature}, timestamp={Timestamp}, nonce={Nonce}",
                    msg_signature, timestamp, nonce);

                var token = _configuration["SenparcWeixinSetting:Token"];
                var encodingAesKey = _configuration["SenparcWeixinSetting:EncodingAESKey"];
                var suiteId = _configuration["SenparcWeixinSetting:SuiteId"];

                if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(encodingAesKey) || string.IsNullOrEmpty(suiteId))
                {
                    _logger.LogError("企业微信配置信息不完整");
                    return BadRequest("配置信息不完整");
                }

                // 读取请求体
                using var reader = new StreamReader(Request.Body, Encoding.UTF8);
                var requestBody = await reader.ReadToEndAsync();

                if (string.IsNullOrEmpty(requestBody))
                {
                    _logger.LogWarning("收到空的回调请求体");
                    return BadRequest("请求体为空");
                }

                _logger.LogDebug("回调请求体: {RequestBody}", requestBody);

                // 使用 WXBizMsgCrypt 解密消息
                var crypt = new WXBizMsgCrypt(token, encodingAesKey, suiteId);
                // Initialize the variable `decryptedXml` to an empty string before passing it to the `DecryptMsg` method.
                string decryptedXml = string.Empty;
                var ret = crypt.DecryptMsg(msg_signature, timestamp, nonce, requestBody, ref decryptedXml);


                if (ret != 0 || string.IsNullOrEmpty(decryptedXml))
                {
                    _logger.LogError("消息解密失败，返回码：{Ret}", ret);
                    return BadRequest("消息解密失败");
                }

                _logger.LogDebug("解密后的XML: {DecryptedXml}", decryptedXml);

                // 解析XML并处理事件
                await ProcessCallbackEvent(decryptedXml);

                return Ok("success");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理企业微信第三方应用回调事件时发生异常");
                return StatusCode(500, "服务器内部错误");
            }
        }

        /// <summary>
        /// 处理企业微信应用回调验证
        /// </summary>
        /// <param name="msg_signature">企业微信加密签名</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        /// <param name="echostr">随机字符串</param>
        /// <returns></returns>
        [HttpGet("corp")]
        public Task<IActionResult> VerifyCorpCallback(
            [FromQuery] string msg_signature,
            [FromQuery] string timestamp,
            [FromQuery] string nonce,
            [FromQuery] string echostr)
        {
            try
            {
                _logger.LogInformation("收到企业微信应用回调验证请求: msg_signature={MsgSignature}, timestamp={Timestamp}, nonce={Nonce}",
                    msg_signature, timestamp, nonce);

                var token = _configuration["SenparcWeixinSetting:Token"];
                var encodingAesKey = _configuration["SenparcWeixinSetting:EncodingAESKey"];
                var corpId = _configuration["SenparcWeixinSetting:CorpId"] ?? "";

                if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(encodingAesKey))
                {
                    _logger.LogError("企业微信配置信息不完整");
                    return Task.FromResult<IActionResult>(BadRequest("配置信息不完整"));
                }

                // 使用 WXBizMsgCrypt 验证签名并解密 echostr
                var crypt = new WXBizMsgCrypt(token, encodingAesKey, corpId);
                var resultEchos = string.Empty;
                var ret = crypt.VerifyURL(msg_signature, timestamp, nonce, echostr, ref resultEchos);

                if (ret == 0 && !string.IsNullOrEmpty(resultEchos))
                {
                    _logger.LogInformation("企业微信应用回调验证成功");
                    return Task.FromResult<IActionResult>(Content(resultEchos));
                }
                else
                {
                    _logger.LogWarning("企业微信应用回调验证失败，返回码：{Ret}", ret);
                    return Task.FromResult<IActionResult>(BadRequest("验证失败"));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理企业微信应用回调验证时发生异常");
                return Task.FromResult<IActionResult>(StatusCode(500, "服务器内部错误"));
            }
        }

        /// <summary>
        /// 处理企业微信应用回调事件
        /// </summary>
        /// <param name="msg_signature">企业微信加密签名</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        /// <returns></returns>
        [HttpPost("corp")]
        public async Task<IActionResult> HandleCorpCallback(
            [FromQuery] string msg_signature,
            [FromQuery] string timestamp,
            [FromQuery] string nonce)
        {
            try
            {
                _logger.LogInformation("收到企业微信应用回调事件: msg_signature={MsgSignature}, timestamp={Timestamp}, nonce={Nonce}",
                    msg_signature, timestamp, nonce);

                var token = _configuration["SenparcWeixinSetting:Token"];
                var encodingAesKey = _configuration["SenparcWeixinSetting:EncodingAESKey"];
                var corpId = _configuration["SenparcWeixinSetting:CorpId"] ?? "";

                if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(encodingAesKey))
                {
                    _logger.LogError("企业微信配置信息不完整");
                    return BadRequest("配置信息不完整");
                }

                // 读取请求体
                using var reader = new StreamReader(Request.Body, Encoding.UTF8);
                var requestBody = await reader.ReadToEndAsync();

                if (string.IsNullOrEmpty(requestBody))
                {
                    _logger.LogWarning("收到空的回调请求体");
                    return BadRequest("请求体为空");
                }

                _logger.LogDebug("回调请求体: {RequestBody}", requestBody);

                // 使用 WXBizMsgCrypt 解密消息
                var crypt = new WXBizMsgCrypt(token, encodingAesKey, corpId);
                string decryptedXml = string.Empty;
                var ret = crypt.DecryptMsg(msg_signature, timestamp, nonce, requestBody, ref decryptedXml);

                if (ret != 0 || string.IsNullOrEmpty(decryptedXml))
                {
                    _logger.LogError("消息解密失败，返回码：{Ret}", ret);
                    return BadRequest("消息解密失败");
                }

                _logger.LogDebug("解密后的XML: {DecryptedXml}", decryptedXml);

                // 解析XML并处理事件
                await ProcessCallbackEvent(decryptedXml);

                return Ok("success");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理企业微信应用回调事件时发生异常");
                return StatusCode(500, "服务器内部错误");
            }
        }

        /// <summary>
        /// 处理回调事件
        /// </summary>
        /// <param name="decryptedXml">解密后的XML</param>
        /// <returns></returns>
        private async Task ProcessCallbackEvent(string decryptedXml)
        {
            try
            {
                var xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(decryptedXml);

                var infoType = xmlDoc.SelectSingleNode("//InfoType")?.InnerText;
                var suiteId = xmlDoc.SelectSingleNode("//SuiteId")?.InnerText;
                var timeStamp = xmlDoc.SelectSingleNode("//TimeStamp")?.InnerText;

                _logger.LogInformation("处理回调事件: InfoType={InfoType}, SuiteId={SuiteId}, TimeStamp={TimeStamp}",
                    infoType, suiteId, timeStamp);

                switch (infoType)
                {
                    case "suite_ticket":
                        await HandleSuiteTicketEvent(xmlDoc);
                        break;
                    case "create_auth":
                        await HandleCreateAuthEvent(xmlDoc);
                        break;
                    case "change_auth":
                        await HandleChangeAuthEvent(xmlDoc);
                        break;
                    case "cancel_auth":
                        await HandleCancelAuthEvent(xmlDoc);
                        break;
                    case "change_contact":
                        await HandleChangeContactEvent(xmlDoc);
                        break;
                    case "change_external_contact":
                        await HandleChangeExternalContactEvent(xmlDoc);
                        break;
                    case "change_external_chat":
                        await HandleChangeExternalChatEvent(xmlDoc);
                        break;
                    default:
                        _logger.LogWarning("未知的回调事件类型: {InfoType}", infoType);
                        break;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理回调事件时发生异常: {DecryptedXml}", decryptedXml);
            }
        }

        /// <summary>
        /// 处理suite_ticket推送事件
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <returns></returns>
        private async Task HandleSuiteTicketEvent(XmlDocument xmlDoc)
        {
            try
            {
                var suiteTicket = xmlDoc.SelectSingleNode("//SuiteTicket")?.InnerText;
                if (!string.IsNullOrEmpty(suiteTicket))
                {
                    await _weChatWorkService.SaveSuiteTicketAsync(suiteTicket);
                    _logger.LogInformation("成功保存SuiteTicket");
                }
                else
                {
                    _logger.LogWarning("SuiteTicket为空");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理suite_ticket事件时发生异常");
            }
        }

        /// <summary>
        /// 处理授权成功通知事件
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <returns></returns>
        private Task HandleCreateAuthEvent(XmlDocument xmlDoc)
        {
            try
            {
                var authCode = xmlDoc.SelectSingleNode("//AuthCode")?.InnerText;
                var authCorpId = xmlDoc.SelectSingleNode("//AuthCorpId")?.InnerText;

                _logger.LogInformation("收到授权成功通知: AuthCode={AuthCode}, AuthCorpId={AuthCorpId}",
                    authCode, authCorpId);

                // 这里可以根据需要处理授权成功后的逻辑
                // 例如：获取授权企业信息、保存到数据库等
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理create_auth事件时发生异常");
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 处理授权变更通知事件
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <returns></returns>
        private Task HandleChangeAuthEvent(XmlDocument xmlDoc)
        {
            try
            {
                var authCode = xmlDoc.SelectSingleNode("//AuthCode")?.InnerText;
                var authCorpId = xmlDoc.SelectSingleNode("//AuthCorpId")?.InnerText;

                _logger.LogInformation("收到授权变更通知: AuthCode={AuthCode}, AuthCorpId={AuthCorpId}",
                    authCode, authCorpId);

                // 这里可以根据需要处理授权变更后的逻辑
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理change_auth事件时发生异常");
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 处理授权取消通知事件
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <returns></returns>
        private Task HandleCancelAuthEvent(XmlDocument xmlDoc)
        {
            try
            {
                var authCorpId = xmlDoc.SelectSingleNode("//AuthCorpId")?.InnerText;

                _logger.LogInformation("收到授权取消通知: AuthCorpId={AuthCorpId}", authCorpId);

                // 这里可以根据需要处理授权取消后的逻辑
                // 例如：清理相关数据、停止服务等
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理cancel_auth事件时发生异常");
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 处理通讯录变更事件
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <returns></returns>
        private Task HandleChangeContactEvent(XmlDocument xmlDoc)
        {
            try
            {
                var changeType = xmlDoc.SelectSingleNode("//ChangeType")?.InnerText;
                var userId = xmlDoc.SelectSingleNode("//UserId")?.InnerText;
                var partyId = xmlDoc.SelectSingleNode("//PartyId")?.InnerText;

                _logger.LogInformation("收到通讯录变更事件: ChangeType={ChangeType}, UserId={UserId}, PartyId={PartyId}",
                    changeType, userId, partyId);

                // 这里可以根据需要处理通讯录变更后的逻辑
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理change_contact事件时发生异常");
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 处理客户联系事件
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <returns></returns>
        private Task HandleChangeExternalContactEvent(XmlDocument xmlDoc)
        {
            try
            {
                var changeType = xmlDoc.SelectSingleNode("//ChangeType")?.InnerText;
                var userId = xmlDoc.SelectSingleNode("//UserId")?.InnerText;
                var externalUserId = xmlDoc.SelectSingleNode("//ExternalUserId")?.InnerText;
                var state = xmlDoc.SelectSingleNode("//State")?.InnerText;

                _logger.LogInformation("收到客户联系事件: ChangeType={ChangeType}, UserId={UserId}, ExternalUserId={ExternalUserId}, State={State}",
                    changeType, userId, externalUserId, state);

                // 这里可以根据需要处理客户联系变更后的逻辑
                // 例如：同步客户信息、发送欢迎消息等
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理change_external_contact事件时发生异常");
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 处理客户群变更事件
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <returns></returns>
        private Task HandleChangeExternalChatEvent(XmlDocument xmlDoc)
        {
            try
            {
                var changeType = xmlDoc.SelectSingleNode("//ChangeType")?.InnerText;
                var chatId = xmlDoc.SelectSingleNode("//ChatId")?.InnerText;
                var owner = xmlDoc.SelectSingleNode("//Owner")?.InnerText;

                _logger.LogInformation("收到客户群变更事件: ChangeType={ChangeType}, ChatId={ChatId}, Owner={Owner}",
                    changeType, chatId, owner);

                // 这里可以根据需要处理客户群变更后的逻辑
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理change_external_chat事件时发生异常");
            }

            return Task.CompletedTask;
        }
    }
}